
package ch.hearc.coursJava.moo.excel;

import org.junit.Assert;

import ch.hearc.coursJava.kitBase.tools.TabTools;

public class RandomIntParallel implements Runnable
    {
    
    /*------------------------------------------------------------------*\
    |*							Constructeurs							*|
    \*------------------------------------------------------------------*/
    
    /**
     * <pre>
     * Tire des nombres entiers al�atoires parallelement
     * L'histogramme des r�sultats se trouve dans un tableau.
     * La m�thode isOk() permet de savoir si les choses se sont bien pass�es ou pas.
     * Tout le travail se fait dans la m�thode run().
     * Cette classe peut donc, au besoin, s'utiliser dans un thread.
     *
     * <b>Exemple 1 :</b>
     * 	RandomIntParallel randomIntParallel = new RandomIntParallel(nbrTirage, borneSup);
     * 	randomIntParallel.run();
     *	if (randomIntParallel.isOk())
     *		{
     *		int[] tabResult = randomIntParallel.getTabResult();
     *		...
     *		}
     *
     * <b>Exemple 2 :</b>
     * 	RandomIntParallel randomIntParallel = new RandomIntParallel(nbrTirage, borneSup);
     * 	Thread thread = new Thread(randomIntParallel);
     * 	thread.start();
     * 	thread.join();
     *
     *	if (randomIntParallel.isOk())
     *		{
     *		int[] tabResult = randomIntParallel.getTabResult();
     *		...
     *		}
     *
     *</pre>
     */
    
    //TODO Impl�menter avec borne inf et borne sup ([a,b])
    public RandomIntParallel(int nbrTirage, int borneSup, int nbrThread)
        {
        // Input
        this.nbrTirage = nbrTirage;
        this.borneSup = borneSup;
        this.nbrThread = nbrThread;
        
        this.isOk = false;
        }
    
    public RandomIntParallel(int nbrTirage, int borneSup)
        {
        this(nbrTirage, borneSup, Runtime.getRuntime().availableProcessors());
        }
    
    /*------------------------------------------------------------------*\
    |*							Methodes Public							*|
    \*------------------------------------------------------------------*/
    
    @Override
    public void run()
        {
        init();
        
        startThreads();
        
        stopThreads();
        
        consolidation();
        }
    
    private void init()
        {
        this.tabRandomInt = new RandomInt[nbrThread];
        this.tabThread = new Thread[nbrThread];
        this.tabResult = new int[borneSup];
        
        for(int i = 0; i < this.tabRandomInt.length; i++)
            {
            RandomInt currentDraw = new RandomInt(nbrTirage / nbrThread, borneSup);
            this.tabRandomInt[i] = currentDraw;
            
            this.tabThread[i] = new Thread(currentDraw);
            }
        }
    
    /*------------------------------*\
    |*				Get				*|
    \*------------------------------*/
    
    public int[] getTabResult()
        {
        return this.tabResult;
        }
    
    /*------------------------------*\
    |*				Is				*|
    \*------------------------------*/
    
    public boolean isOk()
        {
        return this.isOk;
        }
    
    /*------------------------------------------------------------------*\
    |*							Methodes Private						*|
    \*------------------------------------------------------------------*/
    
    private void consolidation()
        {
        for(RandomInt randomInti:this.tabRandomInt)
            {
            int[] currentTabResult = randomInti.getTabResult();
            this.tabResult = TabTools.add(currentTabResult, this.tabResult);
            }
        }
    
    private void stopThreads()
        {
        try
            {
            for(Thread threadi:this.tabThread)
                {
                threadi.join();
                }
            
            this.isOk = true;
            }
        catch (InterruptedException e)
            {
            this.isOk = false;
            }
        }
    
    private void startThreads()
        {
        for(Thread threadi:this.tabThread)
            {
            threadi.start();
            }
        }
    
    /*------------------------------------------------------------------*\
    |*							Attributs Private						*|
    \*------------------------------------------------------------------*/
    
    // Tools
    private RandomInt[] tabRandomInt;
    private Thread[] tabThread;
    
    // Input
    private int nbrTirage;
    private int borneSup;
    private int nbrThread;
    
    // Ouput
    private int[] tabResult;
    private boolean isOk;
    
    public static int[] sumTabValues(int[] src, int[] dst)
        {
        Assert.assertTrue(src.length == dst.length);
        int tabRes[] = new int[src.length];
        for(int i = 1; i <= src.length; ++i)
            {
            tabRes[i - 1] = src[i - 1] + dst[i - 1];
            }
        return tabRes;
        }
    }
